package com;
/**
 * Object 中的方法
 * 
 * wait(): 该线程进入等待状态,交出持有的锁,如果被唤醒之后,接着当前等待的地方继续执行
 * 
 * 必须用在成员方法中,因为是对象相关的,该方法必须加锁(synchronized)
 * 
 * 无参,或者传入0,说明不会自动醒,必须要通过 notify/notifyAll 唤醒
 * 
 * 也可以传入 long 类型的值,单位是毫秒数,多久之后,自动醒来,但是会交出 锁
 * 
 * notify(): 随机唤醒一个在该对象上等待的线程
 * 
 * notifyAll(): 唤醒所有在该对象上等待的线程
 * 
 * 以打印奇数和偶数为例:
 * 
 * 	思路:
 * 		1.有一个业务类 Num,其中有一个整数成员变量 count
 * 		2.业务类提供打印奇数的方法和偶数方法
 * 			1.奇数 printOdd: 打印奇数之和,count++,变成偶数,唤醒其他线程,wait()进入等待并交出锁(可以加睡眠,打印效果更直观一点)
 * 			2.偶数 printEven: 同上
 * 		3.两个线程类,分别去循环调用 printOdd 和 printEven 两个方法,注意,两个线程需要有一个成员变量Num,并且两个线程需要保存同一个对象
 * 
 * @author lenovo
 * @date 2020年7月25日
 */
public class Thread_01_Wait {

	public static void main(String[] args) {
		Num num = new Num(1);
		Thread t1 = new Thread(new PrintOdd(num));
		Thread t2 = new Thread(new PrintOdd(num));
		t1.setName("t1");
		t2.setName("t2");

		t1.start();
		t2.start();
	}

}

//打印奇数线程
class PrintOdd implements Runnable {
	Num num;

	public PrintOdd(Num num) {
		super();
		this.num = num;
	}

	@Override
	public void run() {
		while (true) {
			num.printOdd();
		}
	}

}

//打印偶数线程
class PrintEven implements Runnable {
	Num num;

	public PrintEven(Num num) {
		super();
		this.num = num;
	}

	@Override
	public void run() {
		while (true) {
			num.printEven();
		}
	}

}

class Num {
	int count = 0;//

	public Num(int count) {
		super();
		this.count = count;
	}

	public synchronized void printOdd() {
		System.out.println(Thread.currentThread().getName() + "--->" + count);
		count++;

		notifyAll();
		try {
			Thread.sleep(500);
			wait();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public synchronized void printEven() {
		System.out.println(Thread.currentThread().getName() + "--->" + count);
		count++;

		notifyAll();
		try {
			Thread.sleep(500);
			wait();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}